package com.caption.auth;

import com.caption.auth.secuity.handler.*;
import com.caption.auth.secuity.sms.SmsCodeAuthenticationSecurityConfig;
import com.caption.auth.secuity.username.UsernameAuthenticationProvider;
import com.caption.core.properties.IgnoreUrlProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * @description: springSecurityConfig 认证配置类
 * @author: 码农
 * @date: 2021-12-31 19:55:32
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启权限注解,默认是关闭的
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * 用户登录认证成功处理类
     */
    @Autowired
    private UserAuthSuccessHandler userAuthSuccessHandler;
    /**
     * 用户登录认证失败处理类
     */
    @Autowired
    private UserAuthFailureHandler userAuthFailureHandler;
    /**
     * 用户退出登录处理类
     */
    @Autowired
    private UserLogoutSuccessHandler userLogoutSuccessHandler;
    /**
     * 用户无权限处理类
     */
    @Autowired
    private UserAuthDeniedHandler userAuthDeniedHandler;
    /**
     * 用户未登录处理类
     */
    @Autowired
    private UserAuthenticationEntryPointHandler userAuthenticationEntryPointHandler;
    /**
     * 用户名密码登录认证类
     */
    @Autowired
    private UsernameAuthenticationProvider usernameAuthenticationProvider;
    /**
     * 手机号密码登录处理类
     */
    @Autowired
    private SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig;

    /**
     * 不需要认证的url
     */
    @Autowired
    private IgnoreUrlProperties ignoreUrlProperties;

    /**
     * 配置自己用户名密码登录认证
     * @param auth
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        //这里可启用我们自己的登陆验证逻辑
        auth.authenticationProvider(usernameAuthenticationProvider);
    }

    /**
     * 加密方式
     * @return
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        //配置文件忽略的路径不需要认证
        for (String url : ignoreUrlProperties.getUrls()) {
            http.authorizeRequests().antMatchers(url).permitAll();
        }

        http.apply(smsCodeAuthenticationSecurityConfig)
                .and()
                .authorizeRequests()
                //不需要认证的url
                .antMatchers("/login").permitAll()
                //其他请求需要登录才能访问
                .anyRequest().authenticated()
                .and()
                //配置未登录处理类
                .httpBasic().authenticationEntryPoint(userAuthenticationEntryPointHandler)
                .and()
                //配置账号密码登录地址
                .formLogin().loginProcessingUrl("/user/login")
                //登录认证成功处理类
                .successHandler(userAuthSuccessHandler)
                //登录认证失败处理类
                .failureHandler(userAuthFailureHandler)
                .and()
                //配置账号密码退出登录地址
                .logout().logoutUrl("/user/logout")
                //退出成功处理类
                .logoutSuccessHandler(userLogoutSuccessHandler)
                .and()
                // 配置没有权限自定义处理类
                .exceptionHandling().accessDeniedHandler(userAuthDeniedHandler)
                //开启跨域
                .and()
                .cors()
                // 关闭跨站请求防护
                .and()
                .csrf().disable();

    }

}
